package com.xuexiang.xui_lib.component.edittext;

import ohos.agp.components.AttrHelper;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.Text;
import ohos.agp.components.TextField;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.app.Context;

import com.xuexiang.xui_lib.ResourceTable;
import com.xuexiang.xui_lib.util.AttrValue;
import com.xuexiang.xui_lib.util.TextUtils;

/**
 * 多行计数输入框
 * ignoreCnOrEn 为false的时候
 * 1个中文算1个
 * 2个英文算1个
 * 另外：如：只有一个英文时也算1个
 *
 * @since 2021-04-07
 */
public class MultiLineEditText extends DirectionalLayout {
    private static final int TWOFOURZERO = 240;
    private static final int TEN = 10;
    private static final int FOURTEEN = 14;
    private static final int ONEFOURZERO = 140;
    private static final int ONETWOSEVEN = 127;
    private static final float ZEROFIVE = 0.5F;
    private TextField mEtInput;
    private Text mTvInputNumber;
    private DirectionalLayout mletLayout;

    /**
     * 最大输入的字符数
     */
    private int mMaxCount;
    /**
     * 输入提示文字
     */
    private String mHintText;
    /**
     * 提示文字的颜色
     */
    private int mHintTextColor;
    /**
     * 是否忽略中英文差异
     */
    private boolean mIgnoreCnOrEn;
    /**
     * 输入内容
     */
    private String mContentText;
    /**
     * 输入框文字大小
     */
    private int mContentTextSize;
    /**
     * 输入框文字颜色
     */
    //private int mContentTextColor;
    /**
     * 输入框高度
     */
    private float mContentViewHeight;
    /**
     * 输入框高度是否是固定高度，默认是true
     */
    private boolean mIsFixHeight;
    /**
     * 输入框padding
     */
    private int mContentPadding;
    /**
     * 输入框背景
     */
    private ShapeElement mContentBackground;
    /**
     * 是否显示剩余数目
     */
    private boolean mIsShowSurplusNumber;
    /**
     * mTextWatcher 文字监测
     */
    private Text.TextObserver mTextWatcher = new Text.TextObserver() {
        @Override
        public void onTextUpdated(String s, int i, int i1, int i2) {
            // s:指示当前文本 i:指示要添加的文本的开始位置 i1:指示旧文本的长度。 i2:指示要添加的文本的长度。
            // 先去掉监听器，否则会出现栈溢出
            mEtInput.removeTextObserver(mTextWatcher);
           /* if (mIgnoreCnOrEn) {
                // 当输入字符个数超过限制的大小时，进行截断操作
                if (s.length() > mMaxCount) {
                    mEtInput.setText(s.substring(0, i1));
                }
            } else {
                // 因为是中英文混合，单个字符而言，calculateLength函数都会返回1
                if (s.length() > mMaxCount) { // 当输入字符个数超过限制的大小时，进行截断操作
                    mEtInput.setText(s.substring(0, i1));
                }
            }*/
            if (s.length() > mMaxCount) { // 当输入字符个数超过限制的大小时，进行截断操作
                mEtInput.setText(s.substring(0, i1));
            }
            mEtInput.addTextObserver(mTextWatcher); // 恢复监听器
            configCount(); // update
        }
    };

    /**
     * 构造函数
     *
     * @param context
     */
    public MultiLineEditText(Context context) {
        this(context, null);
    }

    /**
     * 构造函数
     *
     * @param context
     * @param attrSet
     */
    public MultiLineEditText(Context context, AttrSet attrSet) {
        this(context, attrSet, null);
    }

    /**
     * 构造函数
     *
     * @param context
     * @param attrSet
     * @param styleName
     */
    public MultiLineEditText(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        initAttrs(context, attrSet, styleName);
        init();
    }

    /**
     * 初始化属性
     *
     * @param context
     * @param attrSet
     * @param defStyleAttr
     */
    private void initAttrs(Context context, AttrSet attrSet, String defStyleAttr) {
        mMaxCount = AttrValue.get(attrSet, "mlet_maxCount", TWOFOURZERO); // 最大输入文字的数目，默认240
        mIgnoreCnOrEn = AttrValue.get(attrSet, "mlet_ignoreCnOrEn", true); // 是否忽略中英文的差异，默认true
        mHintText = AttrValue.get(attrSet, "mlet_hintText", ""); // 输入框提示文字
        mHintTextColor = AttrValue.get(attrSet, "mlet_hintTextColor",
            ResourceTable.Color_xui_config_color_edittext_hint_text); // 输入框提示文字的颜色
        mContentPadding = AttrValue.get(attrSet, "mlet_contentPadding",
            AttrHelper.vp2px(TEN, context)); // 输入框的padding， 默认10dp
        mContentBackground = AttrValue.get(attrSet, "mlet_contentBackground",
            new ShapeElement(getContext(), ResourceTable.Graphic_mlet_unselector_bg)); // 背景图片
        mContentText = AttrValue.get(attrSet, "mlet_contentText", ""); // 输入框内容
        /*mContentTextColor = AttrValue.get(attrSet, "mlet_contentTextColor",
            ResourceTable.Color_xui_config_color_edittext_input_text); // 文字颜色*/
        mContentTextSize = AttrValue.get(attrSet, "mlet_contentTextSize", AttrHelper.vp2px(FOURTEEN, context));
        mContentViewHeight = AttrValue.get(attrSet, "mlet_contentViewHeight",
            AttrHelper.vp2px(ONEFOURZERO, context)); // 输入框高度
        mIsFixHeight = AttrValue.get(attrSet, "mlet_isFixHeight", true); // 输入框的高度是否是固定高度，默认是true
        mIsShowSurplusNumber = AttrValue.get(attrSet, "mlet_showSurplusNumber", false); // 统计数字显示剩余数目,默认false
    }

    /**
     * 初始化
     */
    private void init() {
        Component view = LayoutScatter.getInstance(getContext())
            .parse(ResourceTable.Layout_xui_layout_multiline_edittext, this, true);
        mEtInput = (TextField) view.findComponentById(ResourceTable.Id_mlet_input);
        mTvInputNumber = (Text) view.findComponentById(ResourceTable.Id_mlet_number);
        mletLayout = (DirectionalLayout) view.findComponentById(ResourceTable.Id_mlet_layout);

        if (getBackgroundElement() == null) {
            setBackground(new ShapeElement(getContext(), ResourceTable.Graphic_mlet_selector_bg));
        }

        mEtInput.addTextObserver(mTextWatcher);
        mEtInput.setHint(mHintText);

        mEtInput.setHintColor(new Color(mHintTextColor));
        mEtInput.setText(mContentText);
        mEtInput.setPadding(mContentPadding, mContentPadding, mContentPadding, 0);
        if (mContentBackground != null) {
            mletLayout.setBackground(mContentBackground);
        }
        mEtInput.setTextSize(mContentTextSize);
        if (mIsFixHeight) {
            mEtInput.setHeight((int) mContentViewHeight);
        } else {
            mEtInput.setMinHeight((int) mContentViewHeight);
        }
        /**
         在mlet_input设置完文本后
         不给mlet_input 焦点
         */
        mTvInputNumber.requestFocus();
        configCount();
        /**
         * focus后给背景设置Selected
         */
        mEtInput.setFocusChangedListener(new FocusChangedListener() {
            @Override
            public void onFocusChange(Component component, boolean b) {
                MultiLineEditText.this.setSelected(b);
                if (b) {
                    mletLayout.setBackground(new ShapeElement(getContext(), ResourceTable.Graphic_mlet_selector_bg));
                } else {
                    mletLayout.setBackground(mContentBackground);
                }
            }
        });
    }

    /**
     * calculateLengthIgnoreCnOrEn
     *
     * @param c1
     * @return int
     */
    private int calculateLengthIgnoreCnOrEn(CharSequence c1) {
        return c1 != null ? c1.length() : 0;
    }

    /**
     * calculateLength
     *
     * @param c
     * @return long
     */
    private long calculateLength(CharSequence c) {
        double len = 0;
        for (int i1 = 0; i1 < c.length(); i1++) {
            int tmp = c.charAt(i1);
            if (tmp > 0 && tmp < ONETWOSEVEN) {
                len += ZEROFIVE;
            } else {
                len++;
            }
        }
        return Math.round(len);
    }

    /**
     * configCount
     */
    private void configCount() {
        if (mIgnoreCnOrEn) {
            int nowCount = calculateLengthIgnoreCnOrEn(mEtInput.getText().toString());
            updateCount(nowCount);
        } else {
            int nowCount = (int) calculateLength(mEtInput.getText().toString());
            updateCount(nowCount);
        }
    }

    /**
     * updateCount
     *
     * @param nowCount
     */
    private void updateCount(int nowCount) {
        if (mIsShowSurplusNumber) {
            mTvInputNumber.setText((mMaxCount - nowCount) + "/" + mMaxCount);
        } else {
            mTvInputNumber.setText(nowCount + "/" + mMaxCount);
        }
    }

    /**
     * 输入的内容是否为空
     *
     * @return boolean
     */
    public boolean isEmpty() {
        return TextUtils.isEmpty(getContentText());
    }

    /**
     * 获取输入的内容
     *
     * @return String
     */
    public String getContentText() {
        if (mEtInput != null) {
            mContentText = mEtInput.getText() == null ? "" : mEtInput.getText().toString();
        }
        return mContentText;
    }
}
